home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 46
/
Amiga Format CD46 (1999-10-20)(Future Publishing)(GB)[!][issue 1999-12].iso
/
-in_the_mag-
/
reader_requests
/
pdflib
/
p_draw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-16
|
5KB
|
209 lines
/* p_draw.c
* Copyright (C) 1997-98 Thomas Merz. All rights reserved.
*
* PDFlib drawing routines
*/
#include <stdio.h>
#include <math.h>
#include "p_intern.h"
/* Section 8.6.1 Path segment operators */
void
PDF_moveto(PDF *p, float x, float y)
{
pdf_end_text(p);
(void) fprintf(p->fp,"%s %s m\n", pdf_float(x), pdf_float(y));
}
void
PDF_lineto(PDF *p, float x, float y)
{
pdf_end_text(p);
(void) fprintf(p->fp,"%s %s l\n", pdf_float(x), pdf_float(y));
}
void
PDF_curveto(PDF *p, float x1, float y1, float x2, float y2, float x3, float y3)
{
pdf_end_text(p);
if (x2 == x3 && y2 == y3) /* second c.p. coincides with final point */
(void) fprintf(p->fp,"%s %s %s %s y\n",
pdf_float(x1), pdf_float(y1), pdf_float(x3), pdf_float(y3));
else /* general case with four distinct points */
(void) fprintf(p->fp,"%s %s %s %s %s %s c\n",
pdf_float(x1), pdf_float(y1),
pdf_float(x2), pdf_float(y2),
pdf_float(x3), pdf_float(y3));
}
/* Convenience routines */
/*
* "Best fit" BCP approximation for an arc segment as suggested
* by Berthold K.P.Horn. Thanks BKPH!
*/
#define ARC_MAGIC 0.5523
#define MIN(x, y) ((x) < (y) ? (x) : (y))
/* PDF_arc() assumes that the current point is already at the arc's start */
void
PDF_arc(PDF *p, float x, float y, float r, float alpha, float beta)
{
float bcp;
float cos_alpha, cos_beta, sin_alpha, sin_beta;
if (r < 0) {
pdf_error(p, PDF_WARN, "Negative circle radius %f", r);
return;
}
if (beta - alpha > 90.0)
{
/* cut down in 90 degree segments until done */
PDF_arc(p, x, y, r, alpha, MIN(alpha + 90, beta));
if (alpha + 90 < beta)
PDF_arc(p, x, y, r, alpha + 90, beta);
return;
}
/* speed up special case for quadrants and circles */
if ((int) alpha == alpha && (int) beta == beta &&
beta - alpha == 90 && (int) alpha % 90 == 0)
{
/* prune angle values */
alpha = (int) alpha % 360;
beta = (int) beta % 360;
switch ((int) alpha) {
case 0:
PDF_curveto(p, x + r, y + r*ARC_MAGIC,
x + r*ARC_MAGIC, y + r, x, y + r);
break;
case 90:
PDF_curveto(p, x - r*ARC_MAGIC, y + r,
x - r, y + r*ARC_MAGIC, x - r, y);
break;
case 180:
PDF_curveto(p, x - r, y - r*ARC_MAGIC,
x - r*ARC_MAGIC, y - r, x, y - r);
break;
case 270:
PDF_curveto(p, x + r*ARC_MAGIC, y - r,
x + r, y - r*ARC_MAGIC, x + r, y);
break;
default:
break;
}
return;
}
alpha = alpha * M_PI / 180; /* convert to radians */
beta = beta * M_PI / 180; /* convert to radians */
/* This formula yields ARC_MAGIC for alpha == 0, beta == 90 degrees */
bcp = 4/3 * (1 - cos((beta - alpha)/2)) / sin((beta - alpha)/2);
sin_alpha = sin(alpha);
sin_beta = sin(beta);
cos_alpha = cos(alpha);
cos_beta = cos(beta);
PDF_curveto(p,
x + r * (cos_alpha - bcp * sin_alpha), /* p1 */
y + r * (sin_alpha + bcp * cos_alpha),
x + r * (cos_beta + bcp * sin_beta), /* p2 */
y + r * (sin_beta - bcp * cos_beta),
x + r * cos_beta, y + r * sin_beta); /* p3 */
}
void
PDF_circle(PDF *p, float x, float y, float r)
{
if (r < 0) {
pdf_error(p, PDF_WARN, "Negative circle radius %f", r);
return;
}
/* draw four Bezier curves to approximate a circle */
PDF_moveto(p, x + r, y);
PDF_curveto(p, x + r, y + r*ARC_MAGIC, x + r*ARC_MAGIC, y + r, x, y + r);
PDF_curveto(p, x - r*ARC_MAGIC, y + r, x - r, y + r*ARC_MAGIC, x - r, y);
PDF_curveto(p, x - r, y - r*ARC_MAGIC, x - r*ARC_MAGIC, y - r, x, y - r);
PDF_curveto(p, x + r*ARC_MAGIC, y - r, x + r, y - r*ARC_MAGIC, x + r, y);
}
void
PDF_rect(PDF *p, float x, float y, float width, float height)
{
pdf_end_text(p);
(void) fprintf(p->fp,"%s %s %s %s re\n",
pdf_float(x), pdf_float(y),
pdf_float(width), pdf_float(height));
}
void
PDF_closepath(PDF *p)
{
pdf_end_text(p);
(void) fputs("h\n", p->fp);
}
/* Section 8.6.2 Path painting operators */
void
PDF_endpath(PDF *p)
{
pdf_end_text(p);
(void) fputs("n\n", p->fp);
}
void
PDF_stroke(PDF *p)
{
pdf_end_text(p);
(void) fputs("S\n", p->fp);
}
void
PDF_closepath_stroke(PDF *p)
{
pdf_end_text(p);
(void) fputs("s\n", p->fp);
}
void
PDF_fill(PDF *p)
{
(void) fputs("f\n", p->fp);
pdf_end_text(p);
}
void
PDF_fill_stroke(PDF *p)
{
pdf_end_text(p);
(void) fputs("B\n", p->fp);
}
void
PDF_closepath_fill_stroke(PDF *p)
{
(void) fputs("b\n", p->fp);
pdf_end_text(p);
}
/* Section 8.6.3 Path clipping operators */
void
PDF_clip(PDF *p)
{
pdf_end_text(p);
(void) fputs("W\n", p->fp);
}